import time
from queue import Queue, Empty
from threading import Thread


def async_task(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target=f, args=args, kwargs=kwargs)
        thr.start()

    return wrapper


class TaskInfo:

    # delay: 延迟执行时间, 单位:秒
    def __init__(self, task_func=None, params=None, callback=None, delay=0):
        self.task_func = task_func
        self.callback = callback
        self.params = params
        self.delay = delay
        self.__execute_time = -1

    @staticmethod
    def current_timestamp():
        t = time.time()
        return round(t * 1000)

    def setup_execute_time(self):
        if self.delay > 0 and self.__execute_time == -1:
            self.__execute_time = self.delay * 1000 + TaskInfo.current_timestamp()

    def execute_time(self):
        return TaskInfo.current_timestamp() >= self.__execute_time


class AsyncTask:

    def __init__(self):
        self.__task_que = Queue()
        self.status_que = Queue()
        self.status_que.put('stop')

    def put_task(self, task_info):
        task_info.setup_execute_time()
        self.__task_que.put(task_info)
        status = self.status_que.get()
        if status == 'stop':
            self.start()
            self.status_que.put('running')
        else:
            self.status_que.put('running')

    @async_task
    def start(self):
        # print('开启任务')
        while True:
            try:
                task_info = self.__task_que.get(timeout=30)
            except Empty as e:
                self.status_que.put('stop')
                # print('任务结束')
                return
            if not isinstance(task_info, TaskInfo):
                print('参数类型错误!!!')
                continue
            try:
                if not task_info.execute_time():
                    time.sleep(0.1)
                    self.put_task(task_info)
                    continue

                func = task_info.task_func
                if func == 'EXIT':
                    return
                if not func:
                    print('请设置要执行的任务')
                    continue
                if task_info.params:
                    result = func(**task_info.params)
                else:
                    result = func()
                if task_info.callback:
                    task_info.callback(result)

            except BaseException as e:
                print(e)

    def stop(self):
        self.put_task(TaskInfo(task_func='EXIT'))

#
# def my_test():
#     print('test函数执行开始')
#     # time.sleep(3)
#     print('test 函数执行结束')
#     return '执行成功', '1'
#
#
# def task_callback(result):
#     print('callback result:', result)
#
#
# def my_print(i):
#     print('task:' + str(i))
#
#
# def test():
#     task = AsyncTask()
#     task.put_task(TaskInfo(task_func=my_test, callback=task_callback, delay=2))
#
#     for i in range(10):
#         ti = TaskInfo()
#         ti.task_func = my_print
#         ti.params = {
#             'i': i,
#         }
#         task.put_task(ti)
#         print(i)
#         time.sleep(1)
#
#     task.stop()
#
#
# test()
